//
//  StringExtension.swift
//  YouCaiShoppingMall
//
//  Created by 优裁科技 on 2017/9/29.
//  Copyright © 2017年 优裁科技. All rights reserved.
//

import CommonCrypto

/**
 * String 扩展
 */
extension String {
    /** 将原始的url编码为合法的url */
    func urlEncoded() -> String {
        return self.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
    }
    
    /** 将编码后的url转换回原始的url */
    func urlDecoded() -> String {
        return self.removingPercentEncoding ?? ""
    }
    
    
    /**
     * 加密设置
     * 例子：
     * 1、shar256 加密：
     * string.hmac(by: .SHA256, key: APP_SECRET.bytes).base64String
     * string.hmac(by: .SHA256, key: APP_SECRET.bytes).hexString
     *
     * 2、MD5加密
     * string.hash(by: .MD5).hexString
     */
    func hmac(by algorithm: Algorithm, key: [UInt8]) -> [UInt8] {
        var result = [UInt8](repeating: 0, count: algorithm.digestLength())
        CCHmac(algorithm.algorithm(), key, key.count, self.bytes, self.bytes.count, &result)
        return result
    }
    
    func hashHex(by algorithm: Algorithm) -> String {
        return algorithm.hash(string: self).hexString
    }
    
    func hash(by algorithm: Algorithm) -> [UInt8] {
        return algorithm.hash(string: self)
    }
    
    
    /// 设置 placeholder 富文本
    /// - Parameter changeText: 改变的文本(全部文本)
    /// - Parameter changFont: 字体
    /// - Parameter changeColor: 颜色
    /// - Parameter isLineThrough: 下划线
    func setPlaceholderAttributeString(ChangeText changeText:String,
                                       withChangeFont changFont:UIFont,
                                       withChangeColor changeColor:UIColor,
                                       isLineThrough:Bool = false) -> NSAttributedString{
        
        let strFullText:String = self
        var dicAttr:[NSAttributedString.Key:Any]?
        let attributeString = NSMutableAttributedString.init(string: strFullText)
        
        //需要改变的文本
        let range = NSString.init(string: strFullText).range(of: changeText)
        
        dicAttr = [
            NSAttributedString.Key.font:changFont,
            NSAttributedString.Key.foregroundColor:changeColor,
        ]
        
        if isLineThrough {
            dicAttr?[NSAttributedString.Key.strikethroughStyle] = NSNumber.init(value: 1)
        }
        attributeString.addAttributes(dicAttr!, range: range)
        
        return attributeString
    }
    
    
    
    /// SQL语句格式化
    /// - Returns: String
    func sqliteEscape() -> String {
        var strInfo = self //',
        strInfo = strInfo.replacingOccurrences(of:"''", with: "\''")
        strInfo = strInfo.replacingOccurrences(of:"',", with: "'',")
        strInfo = strInfo.replacingOccurrences(of:"[", with: "/[")
        strInfo = strInfo.replacingOccurrences(of:"]", with: "/]")
        strInfo = strInfo.replacingOccurrences(of:"%", with: "/%")
        strInfo = strInfo.replacingOccurrences(of:"&", with: "/&")
        //strInfo = strInfo.replacingOccurrences(of:"_", with: "/_")
        strInfo = strInfo.replacingOccurrences(of:"(", with: "/(")
        strInfo = strInfo.replacingOccurrences(of:")", with: "/)")
        return strInfo
    }
    
}


enum Algorithm {
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
    
    func algorithm() -> CCHmacAlgorithm {
        var result: Int = 0
        switch self {
        case .MD5:    result = kCCHmacAlgMD5
        case .SHA1:   result = kCCHmacAlgSHA1
        case .SHA224: result = kCCHmacAlgSHA224
        case .SHA256: result = kCCHmacAlgSHA256
        case .SHA384: result = kCCHmacAlgSHA384
        case .SHA512: result = kCCHmacAlgSHA512
        }
        return CCHmacAlgorithm(result)
    }
    
    func digestLength() -> Int {
        var result: CInt = 0
        switch self {
        case .MD5:    result = CC_MD5_DIGEST_LENGTH
        case .SHA1:   result = CC_SHA1_DIGEST_LENGTH
        case .SHA224: result = CC_SHA224_DIGEST_LENGTH
        case .SHA256: result = CC_SHA256_DIGEST_LENGTH
        case .SHA384: result = CC_SHA384_DIGEST_LENGTH
        case .SHA512: result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
    
    func hash(string: String) -> [UInt8] {
        var hash = [UInt8](repeating: 0, count: self.digestLength())
        switch self {
        case .MD5:    CC_MD5(   string.bytes, CC_LONG(string.bytes.count), &hash)
        case .SHA1:   CC_SHA1(  string.bytes, CC_LONG(string.bytes.count), &hash)
        case .SHA224: CC_SHA224(string.bytes, CC_LONG(string.bytes.count), &hash)
        case .SHA256: CC_SHA256(string.bytes, CC_LONG(string.bytes.count), &hash)
        case .SHA384: CC_SHA384(string.bytes, CC_LONG(string.bytes.count), &hash)
        case .SHA512: CC_SHA512(string.bytes, CC_LONG(string.bytes.count), &hash)
        }
        return hash
    }
}

extension Array where Element == UInt8 {
    var hexString: String {
        return self.reduce(""){$0 + String(format: "%02x", $1)}
    }
    
    var base64String: String {
        return self.data.base64EncodedString(options: Data.Base64EncodingOptions.lineLength76Characters)
    }
    
    var data: Data {
        return Data(self)
    }
}

extension String {
    var bytes: [UInt8] {
        return [UInt8](self.utf8)
    }
}

extension Data {
    var bytes: [UInt8] {
        return [UInt8](self)
    }
}
